package top.mybatisx.sql.core.sql;

import top.mybatisx.sql.core.sql.base.BaseSql;
import top.mybatisx.sql.core.sql.base.JoinEnum;
import top.mybatisx.sql.core.table.CondColumn;
import top.mybatisx.sql.core.table.TableDef;
import top.mybatisx.sql.core.toolkit.ChkUtil;

import java.util.List;

/**
 * 查询
 */
public interface Join<T extends On> extends BaseSql {

    // 连表 sql
    StringBuilder joinSql = new StringBuilder();

    default T leftJoin(Class<? extends TableDef> table) {
        return leftJoin(table, null);
    }

    default T leftJoin(Class<? extends TableDef> table, String alias) {
        return join(JoinEnum.LEFT_JOIN, table, alias);
    }

    default T rightJoin(Class<? extends TableDef> table, String alias) {
        return join(JoinEnum.RIGHT_JOIN, table, alias);
    }

    default T innerJoin(Class<? extends TableDef> table, String alias) {
        return join(JoinEnum.INNER_JOIN, table, alias);
    }

    default T join(Class<? extends TableDef> table, String alias) {
        return (T) join(JoinEnum.JOIN, table, alias);
    }

    default T join(JoinEnum joinEnum, Class<? extends TableDef> table, String alias) {

        // 子类的构造函数,默认包含了 tableName,所以不需要设置
        TableDef tableDef = null;
        try {
            tableDef = table.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        tableDef.setJoinEnum(joinEnum);
        tableDef.setAlias(alias);
        joinList.add(tableDef);
        // map中也设置一份
        tableAliasMap.put(tableDef.getTableName(), alias);

        return (T) this;
    }

    default T joinSql(String sql) {
        joinSql.append(sql);
        return (T) this;
    }

    default String buildJoinSql() {
        if (joinSql.length() > 0 || ChkUtil.isNull(joinList)) {
            // 如果手工设置了 sql, 直接返回
            return joinSql.toString();
        }
        joinSql.setLength(0);

        for (TableDef tableDef : joinList) {
            joinSql.append(" " + tableDef.getJoinEnum().getValue() + " " + tableDef.getTableName());
            if (ChkUtil.isNotNull(tableDef.getAlias())) {
                joinSql.append(" as " + tableDef.getAlias() + " ");
            }

            List<CondColumn> conditionList = tableDef.getJoinConditionList();
            if (conditionList.size() == 0) continue;

            joinSql.append(" on ");
            String allCondSql = getAllCondSql(conditionList);
            joinSql.append(allCondSql);

        }

        return joinSql.toString();
    }
}
